package com.shenhua.kunpeng.aop;


import com.shenhua.kunpeng.annotations.DS;
import com.shenhua.kunpeng.utils.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;

import java.util.Objects;

@Aspect
@Configuration
public class DynamicDataSourceAspect {
  @Pointcut("@annotation(com.shenhua.kunpeng.annotations.DS)")
  public void dataSourcePointCut() {}

  @Pointcut("!@annotation(com.shenhua.kunpeng.annotations.DS) " +
          "&& (execution(* com.shenhua.*.service..*.select*(..)) " +
          "|| execution(* com.shenhua.*.service..*.get*(..)))")
  public void dataSourceReadPointCut() {}

  @Around("dataSourcePointCut()")
  public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    String dsKey = getDSAnnotation(joinPoint).value();
    DynamicDataSourceContextHolder.set(dsKey);
    try{
      return joinPoint.proceed();
    }finally {
      DynamicDataSourceContextHolder.remove();
    }
  }
  @Around("dataSourceReadPointCut()")
  public Object read(ProceedingJoinPoint joinPoint) throws Throwable {
    DynamicDataSourceContextHolder.set("read");
    try{
      return joinPoint.proceed();
    }finally {
      DynamicDataSourceContextHolder.remove();
    }
  }

  /**
   * 根据类或方法获取数据源注解
   */
  private DS getDSAnnotation(ProceedingJoinPoint joinPoint){
    Class<?> targetClass = joinPoint.getTarget().getClass();
    DS dsAnnotation = targetClass.getAnnotation(DS.class);
    // 先判断类的注解，再判断方法注解
    if(Objects.nonNull(dsAnnotation)){
      return dsAnnotation;
    }else{
      MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
      return methodSignature.getMethod().getAnnotation(DS.class);
    }
  }
}
